import { _decorator, Asset, AssetManager, assetManager, AudioClip, Component, Constructor, Node, Prefab } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('ResManager')
export class ResManager {
    private static _instance: ResManager = null;

    static getInstance() {
        if (this._instance === null) {
            this._instance = new ResManager;
        }
        return this._instance;
    }

    public constructor() {

    }

    /**
     * 加载预制体资源
     * @param bundleName 资源包名
     * @param prefabPath 预制体资源路径
     * @param callBack 回调
     */

    loadPrefab(bundleName: string, prefabPath: string, callBack: (prefab: Prefab | null) => void) {
        assetManager.loadBundle(bundleName, (err, bundle) => {
            bundle.load(prefabPath, Prefab, (err, prefab: Prefab) => {
                if (err) {
                    console.error(err);
                    callBack(null);
                    return;
                }
                callBack(prefab);
            })
        })
    }

    /**
     * 加载音频资源
     * @param bundleName 资源包名
     * @param audioPath 音频路径
     * @param callBack 
     */
    loadAudioClip(bundleName: string, audioPath: string, callBack: (audioClip: AudioClip | null) => void) {
        assetManager.loadBundle(bundleName, (err, bundle) => {
            bundle.load(audioPath, AudioClip, (err, audioClip: AudioClip) => {
                if (err) {
                    console.error(err);
                    callBack(null);
                    return;
                }
                callBack(audioClip);
            })
        })
    }

    /**
     * 
     * @param bundleName 
     * @param callBack 
     */
    loadBundle(bundleName: string, callBack?: (bundle: AssetManager.Bundle | null) => void) {
        assetManager.loadBundle(bundleName, (err, bundle) => {
            callBack && callBack(bundle);
        })
    }
    /**
     * 加载 Asset Bundle 接口
     * @param bundleName 
     * @returns 
     */
    loadBundleAsync(bundleName: string): Promise<AssetManager.Bundle> {
        return new Promise<AssetManager.Bundle>(rs => {
            this.loadBundle(bundleName, rs);
        })
    }


    loadPrefabByBUrl(bUrl: IBundleUrl, cb: (prefab: Prefab | null) => void) { this.loadPrefab(bUrl.b, bUrl.u, cb); }
    loadAudioByBUrl(bUrl: IBundleUrl, cb: (audioClip: AudioClip | null) => void) { this.loadAudioClip(bUrl.b, bUrl.u, cb); }

    loadAssetAsync<T extends Asset>(bUrl: IBundleUrl, type: Constructor<T> | null) {
        return new Promise<T>(rs => {
            assetManager.loadBundle(bUrl.b, (err, bundle) => {
                bundle.load(bUrl.u, type, (err, asset: T) => {
                    if (err) {
                        console.error(err);
                        return rs(null);
                    }
                    rs(asset);
                })
            })
        })
    }
}

